/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package library;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author ryan
 */
public class Library {
    private final List<Item> items;
    private final Set<User> users;
    private final List<InventoryChangeListener> listeners;
    private final List<InventoryChangeListener> dateListeners;
    private Date now;
    
    private final int MAX_ITEMS_CHILD = 3;
    private final int MAX_ITEMS_ADULT = 6;
    
   
    public Library(){
        items = new ArrayList<Item>();
        users = new HashSet<User>();
        listeners = new ArrayList<InventoryChangeListener>();
        dateListeners = new ArrayList<InventoryChangeListener>();
        
        //The time defaults to 5:00 pm, Closing time for the library
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 17);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        now = c.getTime();
    }
    
    /**
     * Check out an item to the user.  This removes item
     * from available items and adds it to the user's items
     * @param i
     * @param u 
     */
    public boolean checkout(Item i, User u){
        if(i==null || u==null || i.isCheckedOut()){
            System.out.println("i: " +i+" u:"+u);
            return false;
        }
        
        //Check the number of items the user has checked out
        int numCheckedOut = u.getItems().size();
        if(u.getType()==User.Type.CHILD){
           if(i.getType()==Item.Type.CHILDRENS_BOOK && numCheckedOut<MAX_ITEMS_CHILD){
               i.checkOut(now);
               u.addItem(i);
               for(InventoryChangeListener l:listeners){
                   l.onChange();
               }
               return true;
           }else{
               return false;
           } 
        }else{
            if(numCheckedOut<MAX_ITEMS_ADULT){
                i.checkOut(now);
                u.addItem(i);
                for(InventoryChangeListener l:listeners){
                   l.onChange();
               }
                return true;
            }else{
                return false;
            }            
        }
    }
    
    public void fireUpdateListeners(){
        for(InventoryChangeListener l:listeners){
            l.onChange();
        }       
    }
    
        /**
     * Check an item back in to library
     * @param l
     * @param item
     */
    public void checkin(User user, Item item){
        item.checkIn();        
        user.removeItem(item);
        for(InventoryChangeListener listener:listeners){
            listener.onChange();
        }
    }
    
    public InventoryChangeListener addInventoryChangeListener(InventoryChangeListener l){
        this.listeners.add(l);
        return l;
    }
    
    public void removeInventoryChangeListener(InventoryChangeListener l){
        this.listeners.remove(l);
    }
    
    /**
     * retrieve a list of all the users
     * @return 
     */
    public Set<User> getUsers(){
        return users;
    }
    
    /**
     * Add a user to the library
     * @param u 
     */
    public void addUser(User u){
        users.add(u);
    }
    
    /**
     * Add an item to the library
     * @param i 
     */
    public void addItem(Item i){
        this.items.add(i);
        for(InventoryChangeListener l:listeners){
           l.onChange();
        }
    }
    
    /**
     * get a list of all the checked in items
     * @return 
     */
    public List<Item> getAvailableItems(){
        List<Item> available = new ArrayList<Item>();
        for(Item i:items){
            if(!i.isCheckedOut()){
                available.add(i);
            }
        }
        return available;
    }
    
        /**
     * get a list of all the checked in items
     * @return 
     */
    public List<Item> getAllItems(){
        return items;
    }
    
    
           /**
     * get a list of all the checked in items
     * @return 
     */
    public List<Item> getOverdueItems(){
        List<Item> checkedOut = new ArrayList<Item>();
        for(Item i:items){
            if(i.isCheckedOut() && i.getDueDate().before(getDate())){
                checkedOut.add(i);
            }
        }
        return checkedOut;
    }
    
    public InventoryChangeListener addDateChangeListeners(InventoryChangeListener l){
        this.dateListeners.add(l);
        return l;
    }
    
    /**
     * Set the current date
     * @param d 
     */
    public void setDate(Date d){
        this.now=d;
        for(InventoryChangeListener l: dateListeners){
            l.onChange();
        }
    }
    
    /**
     * Get the current date
     * @return 
     */
    public Date getDate(){
        return now;        
    }
}